package org.wheel.plugins.toolkit.util.sql;

/**
 * SQL降级处理
 * 预处理降级 将 SQL 有多个字段的比较条件进行降级处理,方便Vistor观察模式处理
 *  (a,b) > (c,d)  →  (a > c) OR (a = c AND b > d)
 *  对于大于2个参数的降级,也在这里一起处理
 *
 */

import cn.hutool.core.util.StrUtil;

import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RowComparisonExpander {

    /* 1. 抓 (a,b,c) > (A,B,C) 整体 */
    private static final Pattern ROW_CMP = Pattern.compile(
            "\\(\\s*([^)]+)\\s*\\)\\s*([>=<]+)\\s*\\(\\s*([^)]+)\\s*\\)");

    // 是否匹配
    public static boolean isRowComparison(String sql) {
        Matcher m = ROW_CMP.matcher(sql);
        return m.find();
    }

    /* 2. 入口 */
    public static String expand(String sql) {
        Matcher m = ROW_CMP.matcher(sql);
        StringBuffer sb = new StringBuffer();
        while (m.find()) {
            List<String> left  = splitTrim(m.group(1));
            List<String> right = splitTrim(m.group(3));
            String op          = m.group(2);
            if (left.size() != right.size())
                throw new IllegalArgumentException("左右字段数不一致");
            String replacement = expandRowComparison(left, right, op);
            if(StrUtil.isNotBlank(replacement)){
                replacement = "(" + replacement + ")";
            }
            m.appendReplacement(sb, Matcher.quoteReplacement(replacement));
        }
        m.appendTail(sb);
        return sb.toString();
    }

    /* 3. 按逗号拆分并 trim */
    private static List<String> splitTrim(String csv) {
        return Arrays.stream(csv.split("\\s*,\\s*"))
                .filter(s -> !s.isEmpty())
                .toList();
    }

    /* 4. 字典序展开核心 */
    private static String expandRowComparison(List<String> left,
                                              List<String> right,
                                              String op) {
        StringBuilder sb = new StringBuilder();
        int n = left.size();

        /* 递归构造：(l0>r0) OR (l0=r0 AND l1>r1) OR ... */
        for (int i = 0; i < n; i++) {
            if (i > 0) sb.append(" OR ");
            sb.append('(');
            /* 前面 i 个等式 */
            for (int j = 0; j < i; j++) {
                sb.append('(').append(left.get(j)).append(" = ").append(right.get(j)).append(") AND ");
            }
            /* 第 i 个不等式 */
            String lastOp = mapOp(op, i == n - 1); // 最后一列用原符，前面用 =
            sb.append('(').append(left.get(i)).append(' ').append(lastOp).append(' ').append(right.get(i)).append(')');
            sb.append(')');
        }

        /* 特殊处理 = 和 <> */
        if ("=".equals(op)) {
            return sb.toString().replace("OR", "AND"); // 全等
        }
        if ("<>".equals(op)) {
            /* 任意不等即可，用 OR 保持即可 */
            return sb.toString();
        }
        return sb.toString();
    }

    /* 5. 操作符映射：最后一列用原符，前面用 = */
    private static String mapOp(String op, boolean last) {
        if (!last && ("=".equals(op) || "<>".equals(op))) return "=";
        return op;
    }

    /* 6. 简单测试 */
//    public static void main(String[] args) {
//        String sql = "select * from t where (a, b, c, d) >= (1, 2, 3, 4) and x=9";
//        System.out.println(expand(sql));
//        // 输出：
//        // (a > 1 OR (a = 1 AND b > 2) OR (a = 1 AND b = 2 AND c > 3) OR (a = 1 AND b = 2 AND c = 3 AND d >= 4)) and x=9
//    }
}
